package com.funo.logic.generate.wrapper;

import cn.hutool.core.collection.CollectionUtil;
import com.funo.logic.util.HumpUnderLineUtil;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author 类转化
 */
public class ClassWrapper {

    private static final String BEAN_HOLD_NAME = "$TODO";
    private static final String PACK_NAME_START = "com.funo.entity.";

    /**
     * 类名
     */
    private String name;
    /**
     * 变量名，如User user
     */
    private String shortName;

    private String shortRawName;
    /**
     * 包
     */
    private String packageName;
    /**
     * 全名，保护类的路径
     */
    private String fullName;

    /**
     * 继承类
     */
    private ClassWrapper extendClass;

    /**
     * 引入的其他子类
     */
    private List<ClassWrapper> parameterizedType;

    public static ClassWrapper of(String name) {
        ClassWrapper classWrapper = new ClassWrapper();
        classWrapper.setFullName(name);
        classWrapper.setName(getClassShortRawName(name));
        classWrapper.setShortName(getClassShortName(name));
        classWrapper.setShortRawName(getClassShortRawName(name));
        classWrapper.setPackageName(getClassPackage(name));
        classWrapper.setParameterizedType(getClassParameterizedType(name));
        return classWrapper;
    }

    public static ClassWrapper of(Class clazz) {
        return of(clazz.getName());
    }

    public static ClassWrapper of(String name, String packageName) {
        ClassWrapper classWrapper = new ClassWrapper();
        classWrapper.setName(name);
        classWrapper.setPackageName(packageName);
        classWrapper.setShortName(getClassShortName(name));
        classWrapper.setShortRawName(name);
        return classWrapper;
    }

    protected static String getClassShortName(String name) {

        if (Objects.isNull(name)) {
            return BEAN_HOLD_NAME;
        }
        int index = name.lastIndexOf("<");
        name = index == -1 ? getClassShortRawName(name) : getClassShortRawName(name) + name.substring(index);
        return HumpUnderLineUtil.lowerCaseLetters(name);
    }

    protected static String getClassShortRawName(String name) {

        if (Objects.isNull(name)) {
            return BEAN_HOLD_NAME;
        }
        name = getRawName(name);
        int index = name.lastIndexOf(".");
        return index == -1 ? name : name.substring(index + 1);
    }

    protected static String getClassPackage(String name) {
        if (Objects.isNull(name)) {
            return BEAN_HOLD_NAME;
        }
        if (name.startsWith(PACK_NAME_START)) {
            return PACK_NAME_START + name.toLowerCase();
        }
        name = getRawName(name);
        int index = name.lastIndexOf(".");
        return index == -1 ? null : name.substring(0, index);

    }

    protected static String getRawName(String name) {

        if (Objects.isNull(name)) {
            return BEAN_HOLD_NAME;
        }
        int index = name.lastIndexOf("<");
        name = index == -1 ? name : name.substring(0, index);
        return name;
    }

    protected static List<ClassWrapper> getClassParameterizedType(String name) {

        if (Objects.isNull(name)) {
            return null;
        }
        int index = name.indexOf("<");
        return index == -1 ? Collections.emptyList() :
            Arrays.stream(name.substring(index + 1, name.lastIndexOf(">")).split(","))
                .map(String::trim).map(ClassWrapper::of).collect(Collectors.toList());
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getShortName() {
        return shortName;
    }

    public void setShortName(String shortName) {
        this.shortName = shortName;
    }

    public String getShortRawName() {
        return shortRawName;
    }

    public void setShortRawName(String shortRawName) {
        this.shortRawName = shortRawName;
    }

    public String getPackageName() {
        return packageName;
    }

    public void setPackageName(String packageName) {
        this.packageName = packageName;
    }

    public List<ClassWrapper> getParameterizedType() {
        return parameterizedType;
    }

    public void setParameterizedType(List<ClassWrapper> parameterizedType) {
        this.parameterizedType = parameterizedType;
    }

    public ClassWrapper getExtendClass() {
        return extendClass;
    }

    public void setExtendClass(ClassWrapper extendClass) {
        this.extendClass = extendClass;
    }

    public String getBaseShortName() {
        StringBuilder sb = new StringBuilder();
        sb.append(shortName);

        if (CollectionUtil.isNotEmpty(parameterizedType)) {
            sb.append("<").append(parameterizedType.stream().map(ClassWrapper::getBaseShortName)
                .collect(Collectors.joining(", "))).append(">");
        }

        return sb.toString();
    }

    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }
}
